<?php


/**
 * This class is responsable for taking the parameters from user
 * and prepered it to build a xml and sent that to supplier, after
 * making parser and merge among a lot of results from all suppliers
 *
 * @author fabiano
 * 
 */
require_once SITE_ROOT_PATH."/_lib/classes/class.tree.php";
require_once SITE_ROOT_PATH."/_lib/classes/class.hotel_supplier_low.php";
require_once SITE_ROOT_PATH."/_lib/classes/model/LowSupplier.php";
require_once SITE_ROOT_PATH."/_lib/classes/model/YouSupplier.php";



class SearchHotelController { 
   // This property will have all suppliers
    private $suppliers = array();
    
    /*
     * load all suppliers from hotels.config and figure out some important information about them  
     */
    public function __construct() {
        $suppliersConfigFile = simplexml_load_file(SUPPLIERS_CONFIG_FILE, 'SimpleXMLElement', LIBXML_NOCDATA);
        if ($suppliersConfigFile) {
            foreach ($suppliersConfigFile as $supplierConfig) {                
                $code = (string)$supplierConfig["code"];
                if ( $code == "low") {
                   $supplier = new LowSupplier($supplierConfig);
                if ( $code == "you")
                   $supplier = new YouSupplier($supplierConfig);
                $this->suppliers[$supplier->getCode()] = $supplier; }
            }
        }

    }   
    
    /**
     * This method will be manager of the action Search Hotels. 
     * It will be responsable for creating the XML, send request, parse the result and
     * merge result with results from anothers suppliers
     * @param type $formParams it is params from form
     * @param type $session it says with the research has been executed before, if so just necessary get the session.
     * @return type $results an array with all results from all suppliers.
     */
    
    public function executeActionSearch($formParams, $session) {  
        if ($session){
            $params = $this->preparedParams($formParams);
            $results = array();        
            if (isset($params['search_params']['lowcostbeds_resortID'])){
                foreach ($this->suppliers as $supplier) {
                    $supplier->buildSearchXML(array_merge($params['search_params'],
                                                          $params['destination_values']));  
                    $xml = $supplier->sendSearchRequest();                
                    $results[] =  $supplier->parseXmlSearchResult($xml);                         
                }              
            }
            $results = $this->mergeResults($results, $params);    
            $results['hotels'] = $this->keepHotelWithAllRooms($results['hotels'], $results['rooms_count']);
            $this->createSessionResults($results, $params['search_params']);   
            return $results;            
        } else {
            return $_SESSION["hotels_search_results"]["data"];
        }            
    }
    
    /** 
     * Recive the params from user interface and configure it to process after
     * @param type $params
     * @return type 
     */
    private function preparedParams($params){ 
        $params['guest_children_age'] = $this->map_guest_children_ages($params);
        $day = $params["date_day"];
        $month = substr($params["date_month"],0,2);
        $year = substr($params["date_month"],5,2);
        $params["arrival_date"] = mktime(0, 0, 0, $month, $day, $year); 

        $tree = new tree();
        $destination_values = $tree->get_branch(array('tree_id' => $params["destination_tree_master_id"]), '1');
        $destination_values = $destination_values[0]; 
        $low = new hotel_supplier_low();    
        $locations_low = $low->get_resorts_from_table($params["destination_tree_id"]);
        $resorts_low_list = $this->resort_results_2_list($locations_low,'resort_id');                          
        if ($destination_values['youtravel_id']) {
              $params['youtravel_id'] = $destination_values['youtravel_id'];
        }    

        if ($locations_low[0]['region_id']) {
             $params['lowcostbeds_regionID'] = $locations_low[0]['region_id'];
        }

        if ($resorts_low_list) {
            $params['lowcostbeds_resortID'] = $resorts_low_list;
        } else {
             error_log("[WARNING] SearchHotelController - Message: There's no location in supplier_locations_low to tree_id = " .$params["destination_tree_id"] , 0);
        }    

        return array('search_params'=>$params, 'destination_values' => $destination_values);            

    }
    
    /**
     * It does the merge among results from all suppliers
     * @param type $results Array with all results such as each position is from one exaclty supplier
     * @param type $formParams
     * @return type 
     */
    private function mergeResults($results, $formParams){
        $hotels = array();
        foreach ($results as $hotel) {
             $hotels = array_merge($hotels , $hotel['hotels']);            
        }
        $resultFinal = array ("hotels" => $hotels,
                              "rooms_count" =>intval($formParams['search_params']["no_rooms"]),
                              "nights" => intval($formParams['search_params']["nights"]),
                              "arrival_date" => $formParams['search_params']["arrival_date"],
                              "destination_tree_id" => $formParams['search_params']['destination_tree_id'],
                              "destination_values" => $formParams['destination_values'],
                              "search_params" => $formParams['search_params']);
         // Here we need to improve this method because it's too slow
        $resultFinal = $this->preparedResultsSearch($resultFinal);
             
        return  $resultFinal;
        
    }

    
    /*
     * Temp   
     */
    
    function resort_results_2_list($result,$mykey){
       $resorts = array();   
       if (is_array($result)){
          foreach($result as $value){                
             $resorts[] = $value[$mykey];
         }           
       }
       return $resorts;       
    }  

    /**
     * Set the results from all suppliers such as the key of the position is the same of id of hotel from supplier
     * @param type $params
     * @return type 
     */
    public function preparedResultsSearch($params){
       $res = array();
        foreach ($params['hotels'] as $hotel) {
            $res[$hotel['hotel_id_lowcostbeds']] = $hotel;        
        }
        $params['hotels'] = $res;
        
        $params = $this->multiplyPrices($params);
        
        $params = $this->defaultSort($params); //byPrice
        $params = $this->fetchAdditionalHotelData($params);         
        
        return $params;
    }
    
    public function multiplyPrices($results){
        $coef = COMISSION_PERCENT;        

        foreach ($results["hotels"] as $id=>$hotel) {
            foreach ($hotel["room_sets"] as $room_set_id=>$room_set) {
                if ($room_set["rooms"]) {
                    foreach ($room_set["rooms"] as $i=>$room) {
                        $rateOrig   = $results["hotels"][$id]["room_sets"][$room_set_id]["rooms"][$i]["Rate"];
                        $rateConvert = round($rateOrig, 2, PHP_ROUND_HALF_UP);
                        $rateMarkup= round(($rateConvert + ($rateConvert * $coef)), 2, PHP_ROUND_HALF_UP);
                        // save original price and price with markup
                        $results["hotels"][$id]["room_sets"][$room_set_id]["rooms"][$i]["RateOrig"] = $rateOrig;
                        $results["hotels"][$id]["room_sets"][$room_set_id]["rooms"][$i]["Rate"]     = $rateMarkup;

                        // Board basis desc
                        $bb_code = $results["hotels"][$id]["room_sets"][$room_set_id]["rooms"][$i]["Board"];
                        $results["hotels"][$id]["room_sets"][$room_set_id]["rooms"][$i]["board_desc"] = $this->get_board_basis_description($bb_code);
                    }
                }
            }
        }
        return $results;
    }
    
    public function defaultSort($results) {
        // sort rooms for each hotel
        foreach ($results["hotels"] as $id=>$hotel) {
            $cheapest_room_price = 0;
            foreach ($hotel["room_sets"] as $room_set_id=>$room_set) {
                if ($room_set["rooms"]) {
                    uasort($room_set["rooms"], array($this,"compare_rooms"));
                    $results["hotels"][$id]["room_sets"][$room_set_id] = $room_set;
                    $room = array_shift($room_set["rooms"]);
                    $price = $room["Rate"];
                    if($cheapest_room_price > $price || $cheapest_room_price == 0) {
                        $cheapest_room_price = $price;
                    }
                }
            }
            // remember the cheapest room for each hotel
            $results["hotels"][$id]["cheapest_room"] = $cheapest_room_price;
        }
        // sort hotels by cheapest room
        uasort($results["hotels"], array($this,"compare_hotels"));    
        return $results;
    }
    
    public function fetchAdditionalHotelData($results) {

        if (!is_array($results["hotels"])) {
          return false;
       }
       $hotel_no_match = array();

       foreach ($results["hotels"] as $id => $hotel ) {
 
         $hotel_id = $hotel['hotel_id_lowcostbeds'];
         //unset($params);
         $hotel_supplier_low = new hotel_supplier_low();
         $low_hotel_desc = $hotel_supplier_low->get_hotel_description($hotel_id);
         if (!is_array($low_hotel_desc)){
             error_log("[WARNING] Message: There's no property in supplier_property_low to propertyID = " .$hotel_id , 0);
             $hotel_no_match[] = $hotel_id;
         }
         $hotel['thumb'] = $low_hotel_desc[0]['ThumbnailURL'];
         $hotel['rating'] = $low_hotel_desc[0]['Rating'];
         /* It has to use the local photos */
         //$hotel['thumb'] = $low_hotel_desc[0]['LocalThumbnailURL'];
         $hotel['photos'][] = $low_hotel_desc[0]['LocalImage1URL'];
         $hotel['photos'][] = $low_hotel_desc[0]['LocalImage2URL'];
         $hotel['photos'][] = $low_hotel_desc[0]['LocalImage3URL'];
         $hotel['hotel_name'] = $low_hotel_desc[0]['Property'];
         $hotel['hotel_description'] = $low_hotel_desc[0]['Description'];
         $hotel['hotel_resort'] = $low_hotel_desc[0]['resort'];
         $hotel['hotel_destination'] = $low_hotel_desc[0]['region'];
         $hotel['tree_id'] = $low_hotel_desc[0]['tree_id'];
         $hotel['hotel_id'] = $hotel_id;
         $hotel_array[$id] = $hotel;         
     }

     foreach ($hotel_no_match as $value) {
        unset ($hotel_array[$value]);                     
     }

     $results['hotels'] = $hotel_array;
    
     return $results;
  }
  
    // Probably there's a function that gets it from database
    function get_board_basis_description($bb_code) {
        switch($bb_code){
            case "RO";
                return "Room only";
            break;
            case "SC";
                return "Self catering";
            break;
            case "BB";
                return "Bed & breakfast";
            break;
            case "HB";
                return "Half board";
            break;
            case "AI";
                return "All inclusive";
            break;
            case "FB";
                return "Full Board";
            break;
            default;
                return "$bb_code";
            break;
        }
    }
      
    function compare_rooms($a, $b) {
        if ($a["Rate"]==$b["Rate"]) {
            return 0;
        }
        return ($a["Rate"] < $b["Rate"]) ? -1 : 1;
    }
    
    function compare_hotels($a, $b) {
        if ($a["cheapest_room"] == $b["cheapest_room"]) {
            return 0;
        }
        return ($a["cheapest_room"] < $b["cheapest_room"]) ? -1 : 1;
    }  
    
/**
 * Create the session with the results already configured to use it whithout execute the search again
 * @param type $results 
 */
    private function createSessionResults($results, $formParams){
        $_SESSION["hotels_search_results"] = array("data"=>$results, "timestamp"=>time());                   
        $_SESSION["hotels_search_params"] =  array("data"=>$formParams, "timestamp"=>time());  
       // print_r($_SESSION);// die();
    }
    
    private function keepHotelWithAllRooms($hotels, $rooms){
        $hotelTemp = $hotels; 
        foreach ($hotelTemp as $key => $hotel) {
            if ( count($hotel['room_sets']) < $rooms){
                unset ($hotels[$key]);            
            }
                
        }
        return $hotels;
    }
    
    public function map_guest_children_ages ($params){
        $no_rooms = $params['no_rooms'];
        $ages = array();
        for ($index = 1; $index <= $no_rooms; $index++) {   
            $no_children = $params['room_children_' . $index];
            $age = array();
            for ($i = 1; $i <= $no_children; $i++) {
                $age[$i] = $params['room_children_' . $index .'_age_' . $i];
            }                       
         $ages[$index] = $age;
        }
        return $ages;
    }
}


    
?>
